/**
 * 
 */
package org.xelnaga.defiler.web.servlet.view;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.context.ApplicationContext;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.AbstractUrlBasedView;
import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver;
import org.xelnaga.defiler.web.macro.template.MacroHelperFactory;

/**
 * @author qijb
 *
 */
public class RiotFreeMarkerViewResolver extends FreeMarkerViewResolver {
	private List<ModelPostProcessor> modelPostProcessors = new ArrayList<ModelPostProcessor>();
	
	private boolean autoExposeMacroHelpers = true;
	/**
	 * 
	 */
	public RiotFreeMarkerViewResolver() {
		// TODO Auto-generated constructor stub
	}
	
	/**
	 * Requires {@link RiotFreeMarkerView}.
	 */
	@SuppressWarnings("rawtypes")
	@Override
	protected Class requiredViewClass() {
		return RiotFreeMarkerView.class;
	}

	@Override
	protected void initApplicationContext() {
		super.initApplicationContext();
		if (autoExposeMacroHelpers) {
			modelPostProcessors.add(new MacroHelperExposer(getApplicationContext()));	
		}
		modelPostProcessors.addAll((getApplicationContext().getBeansOfType(ModelPostProcessor.class)).values());		
	}
	
	
	@Override
	protected AbstractUrlBasedView buildView(String viewName) throws Exception {
		RiotFreeMarkerView view = (RiotFreeMarkerView) super.buildView(viewName);
//		view.setAllowModelOverride(allowModelOverride);
//		view.setFreeMarkerServletMode(freeMarkerServletMode);
		view.setModelPostProcessors(modelPostProcessors);
		return view;
	}


	@Override
	public View resolveViewName(String viewName, Locale locale)
			throws Exception {
		View view = super.resolveViewName(viewName, locale);
		return view;
	}


	private static class MacroHelperExposer implements ModelPostProcessor {
		
		private Map<String, MacroHelperFactory> macroHelperFactories;
		
		public MacroHelperExposer(ApplicationContext ctx) {
			macroHelperFactories = ctx.getBeansOfType(MacroHelperFactory.class);
		}
		
		public void postProcess(Map<String, Object> model, 
				HttpServletRequest request, HttpServletResponse response) {
			
			for (Entry<String, MacroHelperFactory> entry : macroHelperFactories.entrySet()) {
				model.put(entry.getKey(), entry.getValue().createMacroHelper(request, response, model));
			}
		}
	}


	public void setModelPostProcessors(List<ModelPostProcessor> modelPostProcessors) {
		this.modelPostProcessors = modelPostProcessors;
	}

	public void setAutoExposeMacroHelpers(boolean autoExposeMacroHelpers) {
		this.autoExposeMacroHelpers = autoExposeMacroHelpers;
	}
	
}
